﻿using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;


namespace XFFSM
{
    public class TransitionLayer : GraphLayer
    {

        #region 字段

        private string currentStateName;
        private FSMController currentController;
        private float transitionTimer = 0;

        private FSMTransition currentTransition = null;

        #endregion

        #region 重写方法


        public override void OnGUI(Rect rect)
        {
            base.OnGUI(rect);

            if (this.Context.RuntimeFSMController == null) {
                return;
            }

            FSMStateNodeData entryState = this.Context.RuntimeFSMController.states.Where(x => x.name.Equals(FSMConst.entryState)).FirstOrDefault();
            FSMStateNodeData defaultState = this.Context.RuntimeFSMController.states.Where(x => x.defaultState== true).FirstOrDefault();

            // 绘制默认过渡
            DrawTransition(entryState, defaultState, Color.yellow);
            // 绘制过渡
            foreach (var item in this.Context.RuntimeFSMController.transitions)
            {
                DrawTransition(item.fromStateName, item.toStateName,item == this.Context.selectTransition ? ColorConst.SelctionColor : Color.white);
            }

            // 绘制预览箭头
            if ( this.Context.isPreviewTransition ) {

                if (this.Context.hoverState == null || 
                    this.Context.hoverState.name.Equals(FSMConst.anyState) ||
                    this.Context.hoverState.name.Equals(FSMConst.entryState))
                {

                    Rect r = GetTransformedRect(this.Context.fromState.rect);
                    DrawTransition(r.center, Event.current.mousePosition, Color.white);
                }
                else {
                    DrawTransition(this.Context.fromState, this.Context.hoverState, Color.white);
                }

            }


            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Delete) {
                if ( this.Context.selectTransition != null ) {
                    FSMTransitionFactory.DeleteTransition(this.Context.RuntimeFSMController,this.Context.selectTransition);
                    this.Context.selectTransition = null;
                }
            }

            DrawStateChangeTransition();
        }

        public override void ProcessEvents()
        {
            base.ProcessEvents();

            if ( this.Context.RuntimeFSMController == null ) { return; }

            if (Event.current.type == EventType.MouseDown && Event.current.button == 0) {
                CheckTransitionClick();
            }
        
        }

        #endregion


        #region 方法


        public TransitionLayer(FSMEditorWindow editorWindow):base(editorWindow) { }

        private void DrawTransition( string fromStateName ,string toStateName,Color color,bool isShowArrow=true, float percent = 1) {
            FSMStateNodeData fromState = this.Context.RuntimeFSMController.states.Where(x => x.name.Equals(fromStateName)).FirstOrDefault();
            FSMStateNodeData toState = this.Context.RuntimeFSMController.states.Where(x => x.name.Equals(toStateName)).FirstOrDefault();
            DrawTransition(fromState, toState, color, isShowArrow, percent);
        }

        private void DrawTransition(FSMStateNodeData startNode,FSMStateNodeData endNode,Color color,bool isShowArrow=true,float percent = 1) {
            if ( startNode == null || endNode == null ) { return; }

            Rect startRect = GetTransformedRect(startNode.rect);
            Rect endRect = GetTransformedRect(endNode.rect);

            Vector2 offset = GetTransitionOffset(startRect, endRect);

            if ( position.Contains(startRect.center + offset) ||
                position.Contains(endRect.center + offset) ||
                position.Contains(startRect.center + offset + (endRect.center - startRect.center) * 0.5f)
                ) {
                Vector2 endPoint = Vector2.Lerp(startRect.center + offset, endRect.center + offset, percent);
                DrawTransition(startRect.center + offset, endPoint, color, isShowArrow);
            }


        }

        private Vector2 GetTransitionOffset( Rect originRect,Rect targetRect ) 
        {
            Vector2 direction = targetRect.center - originRect.center;

            Vector2 offset = Vector2.zero;


            if (Mathf.Abs(direction.y) > Mathf.Abs(direction.x))
            {
                // 上下关系
                offset.x = direction.y < 0 ? 10 : -10;
            }
            else {
                // 左右关系
                offset.y = direction.x > 0 ? 10 : -10;
            }

            return offset * this.Context.ZoomFactor;
        }

        private void DrawTransition( Vector2 startPos,Vector2 end,Color color,bool isShowArrow = true ) {

            Handles.BeginGUI();

            Handles.color = color;

            Handles.DrawAAPolyLine(5f, startPos, end);

            if (isShowArrow) {

                Vector2 direction = end - startPos;
                Vector2 center = startPos + direction * 0.5f;

                Vector2 crossDir = Vector3.Cross(direction, Vector3.forward);

                Vector3[] triangle = { center + direction.normalized * 10,
                                        center + crossDir.normalized *5,
                                        center - crossDir.normalized *5
                };

                Handles.DrawAAConvexPolygon(triangle);

            }

            Handles.EndGUI();

        }

        // 检查过渡点击
        private void CheckTransitionClick() {

            foreach (var item in this.Context.RuntimeFSMController.transitions)
            {

                FSMStateNodeData fromState = this.Context.RuntimeFSMController.states.Where(x => x.name.Equals(item.fromStateName)).FirstOrDefault();
                FSMStateNodeData toState = this.Context.RuntimeFSMController.states.Where(x => x.name.Equals(item.toStateName)).FirstOrDefault();

                Rect startRect = GetTransformedRect(fromState.rect);
                Rect toRect = GetTransformedRect(toState.rect);

                Vector2 offset = GetTransitionOffset(startRect, toRect);
                Vector2 start = startRect.center + offset;
                Vector2 end = toRect.center + offset;

                float width = Mathf.Clamp( Mathf.Abs(end.x - start.x),10, Mathf.Abs(end.x - start.x));
                float height = Mathf.Clamp(Mathf.Abs(end.y - start.y), 10, Mathf.Abs(end.y - start.y));
                Rect rect = new Rect(0, 0, width, height);
                rect.center = start + (end - start) * 0.5f;

                if (rect.Contains(Event.current.mousePosition)) {
                    if (GetMinDistanceToLine(Event.current.mousePosition,start,end) <= 5) {

                        this.Context.selectTransition = item;
                        OnTransitionClick(item);
                        Event.current.Use();
                        break;
                    }
                }

            }

        }


        private float GetMinDistanceToLine(Vector2 point,Vector2 start,Vector2 end) {

            Vector2 v = end - start;
            Vector2 w = point - start;

            Vector2 distance = w - Vector2.Dot(v, w) / v.magnitude * v.normalized;

            return distance.magnitude;
        }


        private void OnTransitionClick(FSMTransitionData transition) {
            FSMTransitionInspectorHelper.Instance.Inspect(this.Context.RuntimeFSMController, transition); 
        }

        // 绘制状态切换过渡
        private void DrawStateChangeTransition() {
            
            if( !Application.isPlaying ){ return; }
            if (this.Context.FSMController == null) { return; }
            if (this.Context.FSMController.currentState== null) { return; }
            if (this.Context.FSMController.currentTransition == null) { return; }

            //if (currentTransition == null) {
            //    currentTransition = this.Context.FSMController.currentTransition;
            //    transitionTimer = 0;
            //    return;
            //}

            if (currentController == null) {
                currentController = this.Context.FSMController;
            }

            // 判断状态机 是否相同 ，
            if (currentController != this.Context.FSMController) {
                currentTransition = this.Context.FSMController.currentTransition;
                transitionTimer = 0;
                currentController = this.Context.FSMController;
                return;
            }
 

            if ( currentTransition == null || 
                !currentTransition.Data.fromStateName.Equals(this.Context.FSMController.currentTransition.Data.fromStateName) ||
                !currentTransition.Data.toStateName.Equals(this.Context.FSMController.currentTransition.Data.toStateName)) {

                //Debug.Log("DrawTransition:"+ transitionTimer);

                transitionTimer += Time.deltaTime * 1.5f;
                if (transitionTimer >= 1) {
                    currentTransition = this.Context.FSMController.currentTransition;
                    transitionTimer = 0;
                }
                // 状态切换了 
                DrawTransition(this.Context.FSMController.currentTransition.Data.fromStateName, this.Context.FSMController.currentTransition.Data.toStateName, ColorConst.TransitionColor, false, transitionTimer);
            }


        }

        #endregion
    }

}

